package com.zmj.sy.mom.srv.aps.utils.order.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.zmj.sy.mom.srv.aps.bean.dto.feign.erp.ErpBaseResDto;
import com.zmj.sy.mom.srv.aps.bean.dto.feign.erp.ErpExternalWwxxResDto;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.base.PhaseJob;
import com.zmj.sy.mom.srv.aps.bean.entity.base.PhaseJobRef;
import com.zmj.sy.mom.srv.aps.bean.entity.base.ProcessChain;
import com.zmj.sy.mom.srv.aps.bean.entity.order.*;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Customer;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Factory;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Phase;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BasePageResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectItemResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.order.*;
import com.zmj.sy.mom.srv.aps.feign.ErpApiClient;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.*;
import com.zmj.sy.mom.srv.aps.utils.order.ExternalOrder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Component
public class ErpExternalOrder implements ExternalOrder {

    private final ErpApiClient erpApiClient;

    private final ImportErpOrderMapper importErpOrderMapper;

    private final ImportErpMaterMapper importErpMaterMapper;

    private final ImportErpBomMapper importErpBomMapper;

    private final ImportErpWorkOrderMapper importErpWorkOrderMapper;

    private final ImportErpWorkOrderDetailMapper importErpWorkOrderDetailMapper;

    private final ImportErpMappingMapper importErpMappingMapper;

    private final OrderMapper orderMapper;

    private final OrderBomMapper orderBomMapper;

    private final OrderPhaseMapper orderPhaseMapper;

    private final OrderPartMapper orderPartMapper;
    private final ImportMbdDxfMapper importMbdDxfMapper;
    private final StringRedisTemplate stringRedisTemplate;
    private final ProcessChainMapper processChainMapper;
    private final ProcessChainItemMapper processChainItemMapper;
    private final CustomerMapper customerMapper;
    private final PhaseJobRefMapper phaseJobRefMapper;
    private final PhaseJobMapper phaseJobMapper;
    private final PhaseMapper phaseMapper;
    private final FactoryMapper factoryMapper;
    private final OrderAccessoriesMapper orderAccessoriesMapper;

    @Override
    public BaseSelectResVo externalSelect(OrderExternalSelectReqVo reqVo) {
        ErpBaseResDto<ArrayList<ImportErpOrder>> resDto = erpApiClient.externalSelect(ErpUtils.getToken());

        if (!resDto.getCode().equals(200)) {
            throw SyExceptionUtils.e("调用ERP接口失败：" + resDto.getMessage());
        }

        List<BaseSelectItemResVo> collect = resDto.getResult()
                .stream()
                .map(e -> {
                    BaseSelectItemResVo vo = new BaseSelectItemResVo();
                    vo.setText(e.getOrderCode());
                    vo.setValue(e.getOrderCode());
                    return vo;
                })
                .collect(Collectors.toList());

        return BaseSelectResVo.of(collect);
    }

    @Transactional
    @Override
    public void externalImport(OrderExternalImportReqVo reqVo) {
        ErpBaseResDto<ArrayList<ImportErpOrder>> resDto = erpApiClient.externalSelect(ErpUtils.getToken());

        if (!resDto.getCode().equals(200)) {
            throw SyExceptionUtils.e("调用ERP接口失败:" + resDto.getMessage());
        }

        List<ImportErpOrder> sale = resDto.getResult()
                .stream()
                .filter(e -> e.getOrderCode().equals(reqVo.getOrderCode()))
                .collect(Collectors.toList());

        if (sale.isEmpty()) {
            throw SyExceptionUtils.e("没有找到该订单");
        }

        if (sale.size() > 1) {
            throw SyExceptionUtils.e("找到多笔订单，请检查数据");
        }

        ImportErpOrder order = sale.get(0);

        ErpBaseResDto<ArrayList<ImportErpMater>> materList = erpApiClient.materList(ErpUtils.getToken(), reqVo.getOrderCode());
//System.out.println("mater:" + JsonUtils.toJsonString(materList));

        if (!materList.getCode().equals(200)) {
            throw SyExceptionUtils.e("调用ERP【物料信息】接口失败");
        }

        if (CollUtil.isEmpty(materList.getResult())) {
            throw SyExceptionUtils.e("没有找到物料信息");
        }

        List<ImportErpMater> topList = materList.getResult()
                .stream()
                .filter(e -> e.getMaterialCode().equals(order.getMaterialCode()))
                .collect(Collectors.toList());

        if (topList.isEmpty()) {
            throw SyExceptionUtils.e("没有找到物料信息");
        }

        if (topList.size() > 1) {
            throw SyExceptionUtils.e("找到多笔物料信息，请检查数据");
        }

        ErpBaseResDto<ArrayList<ImportErpWorkOrder>> workOrderList = erpApiClient.externalGdb(ErpUtils.getToken(), reqVo.getOrderCode());
//System.out.println("workorder:" + JsonUtils.toJsonString(workOrderList));

        if (!workOrderList.getCode().equals(200)) {
            throw SyExceptionUtils.e("调用ERP【工单信息】接口失败");
        }

        for (ImportErpWorkOrder workOrder : workOrderList.getResult()) {
            ErpBaseResDto<ArrayList<ErpExternalWwxxResDto>> wwxxData = erpApiClient.wwxx(ErpUtils.getToken(), reqVo.getOrderCode(), workOrder.getWorkOrderCode());
            workOrder.setIsComponent(wwxxData.getResult() != null ? "1" : "0");
        }

        ErpBaseResDto<ArrayList<ImportErpBom>> orderBomList = erpApiClient.orderBom(ErpUtils.getToken(), reqVo.getOrderCode());
//System.out.println("bom:" + JsonUtils.toJsonString(workOrderList));

        ErpBaseResDto<ArrayList<ImportErpWorkOrderDetail>> workOrderDetailList = erpApiClient.workOrderDetail(ErpUtils.getToken(), reqVo.getOrderCode());


        // 找到老的记录，删除
        List<ImportErpOrder> oldOrder = importErpOrderMapper.selectList(Wrappers.<ImportErpOrder>lambdaQuery().eq(ImportErpOrder::getOrderCode, reqVo.getOrderCode()));
        if (CollUtil.isNotEmpty(oldOrder)) {
            List<Integer> oldOrderIds = oldOrder.stream().map(ImportErpOrder::getId).collect(Collectors.toList());
            importErpOrderMapper.deleteBatchIds(oldOrderIds);
            importErpMaterMapper.delete(Wrappers.<ImportErpMater>lambdaQuery().in(ImportErpMater::getErpOrderId, oldOrderIds));
            importErpWorkOrderMapper.delete(Wrappers.<ImportErpWorkOrder>lambdaQuery().in(ImportErpWorkOrder::getErpOrderId, oldOrderIds));
            importErpBomMapper.delete(Wrappers.<ImportErpBom>lambdaQuery().in(ImportErpBom::getErpOrderId, oldOrderIds));
            importErpWorkOrderDetailMapper.delete(Wrappers.<ImportErpWorkOrderDetail>lambdaQuery().in(ImportErpWorkOrderDetail::getErpOrderId, oldOrderIds));
        }

        // 生成新的记录，保存
        importErpOrderMapper.insert(order);

        for (ImportErpMater importErpMater : materList.getResult()) {
            importErpMater.setErpOrderId(order.getId());
        }
        importErpMaterMapper.insertBatchSomeColumn(materList.getResult());

        for (ImportErpWorkOrder importErpWorkOrder : workOrderList.getResult()) {
            importErpWorkOrder.setErpOrderId(order.getId());
//            importErpWorkOrderMapper.insert(importErpWorkOrder);
        }
        importErpWorkOrderMapper.insertBatchSomeColumn(workOrderList.getResult());

        for (ImportErpBom importErpBom : orderBomList.getResult()) {
            importErpBom.setErpOrderId(order.getId());
            if (order.getMaterialCode().equals(importErpBom.getPmCode())) {
                importErpBom.setIsTop(1);
            } else {
                importErpBom.setIsTop(0);
            }
        }

        Optional<ImportErpBom> firstOption = orderBomList.getResult().stream().filter(e -> e.getIsTop().equals(1)).findFirst();
        ImportErpBom oldTop = firstOption.get();
        if(oldTop.getPmCode() != null ){
            Optional<ImportErpMater> first = materList.getResult().stream()
                    .filter(e -> e.getMaterialCode().equals(oldTop.getPmCode()))
                    .findFirst();

            if(first.isPresent()){
                oldTop.setIsTop(0);

                ImportErpMater importErpMater = first.get();
                ImportErpBom b = new ImportErpBom();
                b.setGrade(importErpMater.getSpec());
                b.setGraphNo(importErpMater.getPaintCode());
                b.setIsTop(1);
                b.setLgort(importErpMater.getLgort());
                b.setMaterial(importErpMater.getMaterial());
                b.setMaterialCode(importErpMater.getMaterialCode());
                b.setMaterialName(importErpMater.getMaterialName());
                b.setOrderCode(oldTop.getOrderCode());
                b.setParentProcess(oldTop.getParentProcess());
                b.setPickCenter(oldTop.getPickCenter());
                b.setPmCode(null);
                b.setStatusId(oldTop.getStatusId());
                b.setErpOrderId(oldTop.getErpOrderId());
                b.setFactory(oldTop.getFactory());
                b.setPmCode("-1");
                Optional<ImportErpWorkOrder> first1 = workOrderList.getResult().stream()
                        .filter(e -> e.getMaterialCode().equals(oldTop.getPmCode()))
                        .findFirst();
                if(first1.isPresent()){
                    ImportErpWorkOrder importErpWorkOrder = first1.get();
                    b.setReqQty(importErpWorkOrder.getQty());
                    b.setPerQty(importErpWorkOrder.getQty());
                    b.setPmQty(importErpWorkOrder.getQty());
                    b.setPickQty("0");
                    b.setPerReqQty(importErpWorkOrder.getQty());
                } else {
                    b.setPmQty("1");
                    b.setReqQty("1");
                    b.setPerQty("1");
                    b.setPerReqQty("1");
                    b.setPickQty("0");
                }
//                b.setWorkOrderCode();
                orderBomList.getResult().add(b);
            }
        }

        importErpBomMapper.insertBatchSomeColumn(orderBomList.getResult());

        for (ImportErpWorkOrderDetail importErpWorkOrderDetail : workOrderDetailList.getResult()) {
            importErpWorkOrderDetail.setErpOrderId(order.getId());
        }
        importErpWorkOrderDetailMapper.insertBatchSomeColumn(workOrderDetailList.getResult());

    }

    @Override
    public BasePageResVo<OrderExternalListResVo> externalList(OrderExternalListReqVo reqVo) {
        LambdaQueryWrapper<ImportErpOrder> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.hasText(reqVo.getOrderCode()), ImportErpOrder::getOrderCode, reqVo.getOrderCode());
        wrapper.orderByDesc(ImportErpOrder::getId);
        Page<ImportErpOrder> importErpOrderPage = importErpOrderMapper.selectPage(reqVo.toPage(), wrapper);

        return BasePageResVo.of(importErpOrderPage, OrderExternalListResVo.class);
    }

    @Override
    public BaseListResVo<OrderExternalBomResVo> externalBom(OrderExternalBomReqVo reqVo) {

        ImportErpOrder order = importErpOrderMapper.selectById(reqVo.getId());

//        QueryWrapper<ImportErpBom> query = Wrappers.query();
//        query.eq("bom.order_code", order.getOrderCode());// 'Z21-010Z'
//        query.eq("bom.pm_code", order.getMaterialCode()); // '60121000386C'
//        query.ne("bom.status_id", "R");// 'Z21-010Z'
//        query.eq("bom.erp_order_id",);
//        query.eq("mater.erp_order_id", reqVo.getId());
//        query.eq("bom.deleted", 0);

//        query.orderByAsc("bom.graph_no");
        List<OrderExternalBomResVo> orderExternalBomResVos = importErpBomMapper.treeList( reqVo.getId());

        List<String> collect = orderExternalBomResVos.stream().map(OrderExternalBomResVo::getPaintCode).distinct().collect(Collectors.toList());
        List<Order> orderList = orderMapper.lambdaQuery()
                .in(Order::getOrderType, 1, 3, 4)
                .eq(Order::getOrderCode, order.getOrderCode())
                .in(Order::getMaterCode, collect).list();
        Map<String, Order> collect1 = orderList.stream().collect(Collectors.toMap(Order::getMaterCode, Function.identity()));

        List<String> cebanOrderList = orderMapper.selectCeban(order.getOrderCode() + "%");
        Order temp = new Order();
        for (String s : cebanOrderList) {
            collect1.put(s, temp);
        }

        for (OrderExternalBomResVo orderExternalBomResVo : orderExternalBomResVos) {
//            if (order.getMaterialCode().equals(orderExternalBomResVo.getPmCode())) {
            if (order.getMaterialCode().equals(orderExternalBomResVo.getMaterialCode())) {
                orderExternalBomResVo.setIsTop(1);
            } else {
                orderExternalBomResVo.setIsTop(0);
            }
            orderExternalBomResVo.setSync(collect1.get(orderExternalBomResVo.getPaintCode()) != null);
        }

        if (orderExternalBomResVos.stream().noneMatch(e -> e.getIsTop().equals(1))) {
            for (OrderExternalBomResVo orderExternalBomResVo : orderExternalBomResVos) {
                if (order.getMaterialCode().equals(orderExternalBomResVo.getPmCode())) {
                    orderExternalBomResVo.setIsTop(1);
                    orderExternalBomResVo.setSync(collect1.get(orderExternalBomResVo.getPaintCode()) != null);
                }
            }
        }

        Map<String, List<OrderExternalBomResVo>> pmCodeMap = orderExternalBomResVos.stream().collect(Collectors.groupingBy(OrderExternalBomResVo::getPmCode));

        List<OrderExternalBomResVo> all = new ArrayList<>();
        List<OrderExternalBomResVo> parentList = orderExternalBomResVos.stream().filter(e->e.getIsTop().equals(1)).collect(Collectors.toList());
        while (!CollUtil.isEmpty(parentList)) {
            all.addAll(parentList);
            List<OrderExternalBomResVo> tempArr = new ArrayList<>();
            for (OrderExternalBomResVo e : parentList) {
                List<OrderExternalBomResVo> children = pmCodeMap.get(e.getMaterialCode());
                if (CollUtil.isNotEmpty(children)) {
                    tempArr.addAll(children);
                }
            }

            parentList = tempArr;
        }

        if (CollUtil.isNotEmpty(all)) {
            Map<String, OrderExternalBomResVo> map = all.stream().filter(e->StringUtils.hasText(e.getPaintCode())).collect(Collectors.toMap(e -> e.getMaterialCode() + "$$$" + e.getPmCode(), Function.identity(), (e1, e2) -> e1));
            all = new ArrayList<>(map.values());
        }

        all.sort(Comparator.comparing(OrderExternalBomResVo::getPaintCode));

        return new BaseListResVo<>(all);
    }

    @Override
    public BaseListResVo<OrderExternalDetailResVo> externalDetail(OrderExternalDetailReqVo reqVo) {
        ImportErpBom importErpBom = importErpBomMapper.selectById(reqVo.getId());

        List<ImportErpBom> all = new ArrayList<>();
        List<ImportErpBom> children = new ArrayList<>();
        children.add(importErpBom);

        // 遍历子节点
        while (CollUtil.isNotEmpty(children)) {
            all.addAll(children);

            List<ImportErpBom> allBomTree = importErpBomMapper.lambdaQuery()
                    .in(ImportErpBom::getPmCode, children.stream().map(ImportErpBom::getMaterialCode).distinct().collect(Collectors.toList()))
                    .eq(ImportErpBom::getErpOrderId, importErpBom.getErpOrderId())
                    .ne(ImportErpBom::getStatusId, "R")
                    .list();

            children = new ArrayList<>(allBomTree);
        }

        if (CollUtil.isEmpty(all)) {
            return BaseListResVo.empty();
        }

        List<ImportErpMater> materList = importErpMaterMapper.lambdaQuery()
                .in(ImportErpMater::getMaterialCode, all.stream().map(ImportErpBom::getMaterialCode).distinct().collect(Collectors.toList()))
                .eq(ImportErpMater::getErpOrderId, importErpBom.getErpOrderId())
                .list();

        Map<String, ImportErpMater> materMap = materList.stream().collect(Collectors.toMap(ImportErpMater::getMaterialCode, Function.identity(), (e1, e2) -> e1));

        List<OrderExternalDetailResVo> collect = all.stream()
                .filter(e-> !e.getMaterialCode().matches("^(010|020|050|060).+$"))
                .map(e -> {
                    OrderExternalDetailResVo r = new OrderExternalDetailResVo();

                    r.setFactoryCode(e.getFactory());
                    r.setOrderCode(e.getOrderCode());
                    r.setWorkOrderCode(e.getWorkOrderCode());
                    r.setMaterCode(e.getMaterialCode());
                    r.setMaterName(e.getMaterialName());
                    r.setPerQty(e.getPerQty());
                    r.setReqQty(e.getReqQty());
                    r.setLgort(e.getLgort());
                    r.setParentMaterCode(e.getPmCode());
                    r.setCreateDateTime(e.getCreateDateTime());
                    r.setStatusId(e.getStatusId());
                    r.setPerReqQty(e.getPerReqQty());
                    r.setPickQty(e.getPickQty());
                    r.setPickCenter(e.getPickCenter());

                    ImportErpMater importErpMater = materMap.get(e.getMaterialCode());
                    if (importErpMater == null) {
                        r.setDrawing(e.getGraphNo());
                        r.setPlmId(e.getGraphNo());
                        return r;
                    }

                    r.setPlmId(importErpMater.getPlmId());
                    return r;
                })
                .collect(Collectors.toList());

        return new BaseListResVo<>(collect);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void externalSync(OrderExternalSyncReqVo reqVo) {

        List<OrderExternalSyncErrorResVo> errorList = new ArrayList<>();

        ImportErpBom currentBom = importErpBomMapper.selectById(reqVo.getId());
        if (currentBom == null) {
            throw SyExceptionUtils.e("没有找到该节点，请刷新后重试");
        }

        if ("R".equals(currentBom.getStatusId())) {
            throw SyExceptionUtils.e("该节点状态异常");
        }

        ImportErpOrder importErpOrder = importErpOrderMapper.selectById(currentBom.getErpOrderId());

        // 获取所有的子节点
        List<ImportErpBom> allBomTree = findAllTree(importErpOrder);

        // 获取可用的的子节点
        List<ImportErpBom> bomChildren = findBomChildren(currentBom);

        List<String> materCodeList = bomChildren.stream().map(ImportErpBom::getMaterialCode).collect(Collectors.toList());

        // 获取所有的物料信息组成Map，供BOM使用
        List<ImportErpMater> materList = getMaterMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工单信息组成Map，供BOM使用
        List<ImportErpWorkOrder> erpWorkOrderList = getWorkOrderMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工单明细组成Map，供BOM使用
        List<ImportErpWorkOrderDetail> workOrderDetailList = getWorkOrderDetailMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工序映射，供BOM使用
        List<ImportErpMapping> importErpMappings = importErpMappingMapper.selectList(null);

        // 转换订单
        Optional<ImportErpMater> first = materList.stream().filter(e -> e.getMaterialCode().equals(currentBom.getMaterialCode())).findFirst();
        if (!first.isPresent()) {
            throw SyExceptionUtils.e("找不到对应的物料信息");
        }
        Order order = conversionOrder(importErpOrder, currentBom, first.get(), errorList);

        // 判断是否重复
        String pattern = ".+" + WorkshopProp.PH_PATTERN;
        List<String> assList = bomChildren.stream()
                .map(ImportErpBom::getGraphNo)
                .filter(graphNo -> graphNo.matches(pattern))
                .distinct()
                .collect(Collectors.toList());

        Map<String, ImportErpBom> collect = allBomTree.stream().collect(Collectors.toMap(ImportErpBom::getMaterialCode, Function.identity(), (e1, e2) -> e1));
        ImportErpBom parentTemp = collect.get(currentBom.getMaterialCode());
        while (parentTemp != null) {
            assList.add(parentTemp.getGraphNo());
            parentTemp = collect.get(parentTemp.getPmCode());
        }

        Integer ct = orderMapper.lambdaQuery()
                .eq(Order::getConstructNo, order.getConstructNo())
                .in(Order::getMaterCode, assList)
                .in(Order::getOrderType, 1, 3, 4)
                .count();
        if (ct > 0) {
            throw SyExceptionUtils.e("该订单已重复或者重叠，请勿重复同步。");
        }

        // 判断是否重复导入，
        ArrayList<String> dyz = Lists.newArrayList("D", "Y", "Z");
        if (order.getOrderType().equals(1) && !dyz.contains(order.getSuffix())) {
            Integer serialNum = getSerialNum(order.getConstructNo(), order.getOrderType());
            order.setSerialNum(serialNum);
            order.setSerialCode(String.format("%04d-", order.getSerialNum()) + order.getConstructNo());
            order.setMaterCode(order.getConstructNo() + order.getSuffix());
            order.setMaterName(OrderUtils.partName(order.getSuffix()));
            Order oldOrder = orderMapper.lambdaQuery()
                    .eq(Order::getConstructNo, order.getConstructNo())
                    .eq(Order::getMaterCode, order.getMaterCode())
                    .one();

            // 重复验证订单是否重复，修补上个逻辑
            if (oldOrder != null) {
                if (order.getOrderQty() < oldOrder.getOrderQty()) {
                    throw SyExceptionUtils.e("同步的件数比原订单数量还少");
                }

                order = oldOrder;

                if (oldOrder.getOrderStatus() > 2) {
                    throw SyExceptionUtils.e("该订单进入排产，无法再同步。");
                }

                OrderBom orderBom = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, oldOrder.getId()).isNull(OrderBom::getPid).one();
                if (orderBom != null) {
                    List<OrderBom> secondBomList = orderBomMapper.lambdaQuery()
                            .eq(OrderBom::getOrderId, oldOrder.getId())
                            .eq(OrderBom::getPid, orderBom.getId())
                            .list();
                    List<OrderBom> collect1 = secondBomList.stream().filter(e -> e.getMaterCode().equals(currentBom.getGraphNo())).collect(Collectors.toList());
                    if (!CollUtil.isEmpty(collect1)) {
                        throw SyExceptionUtils.e("该订单已同步，请勿重复同步。");
                    }

                }
            } else {
                orderMapper.insert(order);
            }
        } else {

            // 删除老的
            Order oldOrder = orderMapper.lambdaQuery()
                    .eq(Order::getConstructNo, order.getConstructNo())
                    .eq(Order::getMaterCode, order.getMaterCode())
                    .in(Order::getOrderType, 1, 3, 4)
                    .one();

            if(oldOrder != null && oldOrder.getOrderStatus() > 2){
                throw SyExceptionUtils.e("已存在该订单，请删除再同步!");
            }

            if (oldOrder != null) {
                orderMapper.deleteReal(oldOrder.getId());
                orderBomMapper.deleteReal(oldOrder.getId());
                orderPhaseMapper.deleteReal(oldOrder.getId());
                orderAccessoriesMapper.deleteReal(oldOrder.getId());
            }

            // 保存订单
            saveOrder(order, errorList);
        }

        // 转换BOM
        List<OrderBom> orderBomList = conversionBom(order, importErpOrder, allBomTree, bomChildren, materList, erpWorkOrderList, workOrderDetailList, importErpMappings, errorList);


        if(order.getConstructNo().endsWith("S") && order.getOrderType().equals(1) && !dyz.contains(order.getSuffix())){
            OrderBom orderBom = orderBomList.stream().filter(e -> e.getLevel() == 2).min(Comparator.comparing(OrderBom::getPartCount)).get();
            BigDecimal partCount = orderBom.getPartCount();
            order.setOrderQty(partCount.intValue());
            orderBomMapper.lambdaUpdate()
                    .eq(OrderBom::getId, orderBom.getId())
                    .set(OrderBom::getTotalCount, new BigDecimal(1))
                    .set(OrderBom::getPartCount, new BigDecimal(1))
                    .update();

            List<OrderBom> collect1 = orderBomList.stream().filter(e -> e.getLevel() > 2).collect(Collectors.toList());
            for (OrderBom bom : collect1) {
                orderBomMapper.lambdaUpdate()
                        .eq(OrderBom::getId, bom.getId())
                        .set(OrderBom::getTotalCount, bom.getTotalCount().divide(partCount, 0, RoundingMode.HALF_UP))
                        .update();

            }

            orderMapper.updateById(order);

        }

        // 转换零件
        savePart(orderBomList, order, materList, erpWorkOrderList, workOrderDetailList, importErpMappings, errorList);

        // 转换工序
        List<OrderPhase> orderPhaseList = conversionPhase(order, orderBomList, workOrderDetailList, importErpMappings, errorList);
        savePhase(orderPhaseList);

        // 转换并保存辅料
        conversionAndSaveAccessories(order, orderBomList, errorList, currentBom, orderPhaseList);
//        saveAccessories(orderPhaseList);

        String key = "mom-srv-aps:order-sync:error:" + order.getConstructNo() + ":" + first.get().getPlmId();
        if (CollUtil.isNotEmpty(errorList)) {
            // 存redis
            stringRedisTemplate.opsForValue()
                    .set(key, JsonUtils.toJsonString(errorList), 10, TimeUnit.DAYS);

            throw SyExceptionUtils.e("同步失败，请查看Excel的错误信息");
        }
        stringRedisTemplate.delete(key);

    }

    public List<OrderAccessories> conversionAndSaveAccessories(Order order, List<OrderBom> orderBomList, List<OrderExternalSyncErrorResVo> errorList, ImportErpBom currentBom, List<OrderPhase> orderPhaseList) {

        List<ImportErpBom> importErpBoms = importErpBomMapper.treeAll(currentBom.getErpOrderId());

        Map<String, List<ImportErpBom>> pmCodeList = importErpBoms.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));

        List<ImportErpBom> l = new ArrayList<>();

        List<ImportErpBom> temp = new ArrayList<>();
        temp.add(currentBom);
        currentBom.setIsTop(1);

        while (!temp.isEmpty()) {
            List<ImportErpBom> t = new ArrayList<>();
            for (ImportErpBom importErpBom : temp) {
                List<ImportErpBom> importErpBoms1 = pmCodeList.get(importErpBom.getMaterialCode());
                if (importErpBoms1 == null) {
                    continue;
                }
                for (ImportErpBom erpBom : importErpBoms1) {
                    erpBom.setIsTop(0);
                }
                t.addAll(importErpBoms1);
            }
            l.addAll(temp);
            temp = t;
        }

        Map<String, OrderBom> collect = orderBomList.stream().collect(Collectors.toMap(OrderBom::getErpCode, Function.identity(), (e1, e2) -> e1));

        Map<Integer, Map<String, OrderPhase>> phaseBomIdPhaseCodeMap = orderPhaseList.stream().filter(e->e.getPhaseCode().equals("PT")).collect(Collectors.groupingBy(OrderPhase::getBomId, Collectors.toMap(OrderPhase::getPhaseCode, e -> e)));

        List<OrderAccessories> orderAccessoriesList = l.stream()
                .filter(e -> e.getMaterialCode().matches("^(010|020|050|060).+$"))
                .map(e -> {
                    OrderAccessories oa = new OrderAccessories();
                    oa.setOrderType(order.getOrderType());
                    oa.setOrderId(order.getId());
                    oa.setMaterCode(e.getMaterialCode());
                    oa.setMaterName(e.getMaterialName());
                    oa.setSpec(e.getGrade());
                    oa.setModel(e.getGraphNo());
                    oa.setMaterial(e.getMaterial());
                    oa.setPartCount(new BigDecimal(e.getReqQty()));
                    oa.setType(Integer.parseInt(e.getMaterialCode().substring(0, 2)));

                    OrderBom orderBom = collect.get(e.getPmCode());
                    if (orderBom == null) {
                        return oa;
                    }
                    oa.setBomId(orderBom.getId());

                    if(e.getMaterialCode().startsWith("050")){
                        Map<String, OrderPhase> stringOrderPhaseMap = phaseBomIdPhaseCodeMap.get(oa.getBomId());
                        if(stringOrderPhaseMap == null){
                            return oa;
                        }

                        OrderPhase orderPhase = stringOrderPhaseMap.get("PT");
                        oa.setPhaseId(orderPhase.getId());
                        oa.setPhaseCode(orderPhase.getPhaseCode());
                    }

                    return oa;
                })
                .collect(Collectors.toList());

        Map<Integer, Map<String, OrderAccessories>> collect1 = orderAccessoriesList.stream().filter(e -> e.getMaterCode().startsWith("020")).collect(Collectors.groupingBy(OrderAccessories::getBomId, Collectors.toMap(OrderAccessories::getMaterCode, e -> e, (e1, e2)-> e1)));

        Map<Integer, OrderBom> orderBomIdMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getId, Function.identity()));
        List<OrderAccessories> oaHansi = orderPhaseList.stream()
                .filter(e -> CollUtil.isNotEmpty(e.getAttr()) && e.getAttr().get("type").equals("wire"))
                .map(e -> {
                    OrderBom orderBom = orderBomIdMap.get(e.getBomId());
                    OrderAccessories oa = new OrderAccessories();
                    oa.setOrderType(order.getOrderType());
                    oa.setOrderId(order.getId());
                    oa.setBomId(orderBom.getId());
                    oa.setPhaseId(e.getId());
                    oa.setPhaseCode(e.getPhaseCode());
                    oa.setType(2);
                    oa.setMaterCode(e.getAttr().get("wirenumber"));
                    oa.setModel(e.getAttr().get("wiremodel"));
                    oa.setPartCount(new BigDecimal(e.getAttr().get("wirequota")));

                    Map<String, OrderAccessories> stringOrderAccessoriesMap = collect1.get(orderBom.getId());
                    if (stringOrderAccessoriesMap == null) {
                        return oa;
                    }

                    OrderAccessories accessories = stringOrderAccessoriesMap.get(oa.getMaterCode());
                    if (accessories == null) {
                        return oa;
                    }

                    oa.setMaterName(accessories.getMaterName());
                    oa.setSpec(accessories.getSpec());
                    oa.setMaterial(accessories.getMaterial());
                    return oa;

                })
                .collect(Collectors.toList());

        List<OrderAccessories> all = orderAccessoriesList.stream().filter(e -> !e.getMaterCode().startsWith("020")).collect(Collectors.toList());
        if(CollUtil.isNotEmpty(oaHansi)){
            all.addAll(oaHansi);
        }

        orderAccessoriesMapper.insertBatch(all);

        return orderAccessoriesList;
    }

    public List<ImportErpBom> findBomChildren2(ImportErpBom currentBom) {
//
//        QueryWrapper<ImportErpBom> query = Wrappers.query();
//        query.ne("bom.status_id", "R");// 'Z21-010Z'
//        query.eq("bom.erp_order_id", currentBom.getErpOrderId());
////        query.eq("mater.erp_order_id", currentBom.getErpOrderId());
//        query.eq("bom.deleted", 0);
//        query.orderByAsc("mater.paint_code");
        List<ImportErpBom> importErpBoms = importErpBomMapper.tree(currentBom.getErpOrderId());

        Map<String, List<ImportErpBom>> pmCodeList = importErpBoms.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));

        List<ImportErpBom> l = new ArrayList<>();

        List<ImportErpBom> temp = new ArrayList<>();
        temp.add(currentBom);
        currentBom.setIsTop(1);

        while (!temp.isEmpty()) {
            List<ImportErpBom> t = new ArrayList<>();
            for (ImportErpBom importErpBom : temp) {
                List<ImportErpBom> importErpBoms1 = pmCodeList.get(importErpBom.getMaterialCode());
                if (importErpBoms1 == null) {
                    continue;
                }
                for (ImportErpBom erpBom : importErpBoms1) {
                    erpBom.setIsTop(0);
                }
                t.addAll(importErpBoms1);
            }
            l.addAll(temp);
            temp = t;
        }
        return l;
    }

    public void saveWorkChain(List<OrderBom> orderBomList, List<OrderPhase> orderPhaseList, Order order, List<OrderExternalSyncErrorResVo> errorList) {


        List<String> collect = orderBomList.stream().map(OrderBom::getWorkChain).distinct().collect(Collectors.toList());
        if(CollUtil.isEmpty(collect)){
            return ;
        }

        List<ProcessChain> list = processChainMapper.lambdaQuery().in(ProcessChain::getMyCode, collect).list();
        Map<String, ProcessChain> processChainMap = list.stream().collect(Collectors.toMap(ProcessChain::getMyCode, Function.identity()));

        List<String> workChainList = collect.stream().filter(e -> e != null && processChainMap.get(e) == null).collect(Collectors.toList());

        Map<String, OrderBom> bomMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getWorkChain, Function.identity(), (e1, e2) -> e1));
        Map<Integer, List<OrderPhase>> phaseMap = orderPhaseList.stream().collect(Collectors.groupingBy(OrderPhase::getBomId));

        for (String workChain : workChainList) {
            OrderBom orderBom = bomMap.get(workChain);
            if(orderBom.getWorkChain().equals("WL")){
                continue;
            }

            if(!StringUtils.hasText(orderBom.getWorkChain())){
                continue;
            }
            List<OrderPhase> phaseList = phaseMap.get(orderBom.getId());
            if(CollUtil.isEmpty(phaseList)){
                return ;
            }

            /*
            ProcessChain processChain = new ProcessChain();
            processChain.setMyCode(workChain);
            processChain.setName(workChain);
            processChainMapper.insert(processChain);


            if(CollUtil.isEmpty(phaseList) && orderBom.getWorkChain().equals(WorkshopProp.WW_PHASE_CODE)){
                return ;
            }
            phaseList.sort(Comparator.comparing(OrderPhase::getPhaseSeq));

            List<ProcessChainItem> collect1 = phaseList.stream().map(e -> {
                ProcessChainItem item = new ProcessChainItem();
                item.setChainId(processChain.getId());
                item.setName(e.getPhaseName());
                item.setMyCode(e.getPhaseCode());
                item.setSeq(e.getPhaseSeq());
                return item;
            }).collect(Collectors.toList());

            processChainItemMapper.insertBatch(collect1);

             */

        }


    }

    public void savePart(List<OrderBom> orderBomList, Order order, List<ImportErpMater> materList, List<ImportErpWorkOrder> erpWorkOrderList, List<ImportErpWorkOrderDetail> workOrderDetailList, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {
        List<String> collect = orderBomList.stream().map(OrderBom::getPlmId).distinct().collect(Collectors.toList());
        List<OrderPart> hasPartList = orderPartMapper.lambdaQuery().in(OrderPart::getPlmId, collect).list();
        Map<String, OrderPart> hasPartMap = hasPartList.stream().collect(Collectors.toMap(OrderPart::getPlmId, Function.identity()));
        // 判断表中有没有，没有就全量写入，有就跳过该条
        List<OrderPart> orderParts = new ArrayList<>();
        for (OrderBom orderBom : orderBomList) {

            OrderPart orderPart = hasPartMap.get(orderBom.getPlmId());
            if (orderPart != null) {
                continue;
            }

            orderPart = new OrderPart();
            orderPart.setType(2); // 普通件
            orderPart.setNetWeight(orderBom.getMaterWeight());
            // orderPart.setArea(); // 面积
            orderPart.setWorkChain(orderBom.getWorkChain()); // 工序链
            orderPart.setSource(orderBom.getReadyType()); // 备料方式：1 自制  2 外购
            // orderPart.setCritical(); // 是否关键件 0不是 1是
            orderPart.setVersionCode(1L); // 版本号
            orderPart.setMaterType(orderBom.getMaterType()); // 物料类别
            orderPart.setPlmId(orderBom.getPlmId());
            // orderPart.setPngUrl(); // 零件PNG图纸路径
            // orderPart.setDxfUrl(); // 零件DXF图纸路径
            orderPart.setDrawing(orderBom.getDrawing());
            if (!Objects.equals(orderBom.getMaterType(), "Platepart")) {
                orderPart.setTexture(orderBom.getTexture());
            } else {
                String[] split = orderBom.getStandards().split("δ");
                if (orderBom.getTexture() != null) {
                    orderPart.setTexture(orderBom.getTexture());
                } else {
                    orderPart.setTexture(split[0]);
                }
                if (orderBom.getMaterHigh() != null) {
                    orderPart.setThickness(new BigDecimal(orderBom.getMaterHigh()));
                } else {
                    orderPart.setThickness(new BigDecimal(split[1]));
                }
            }
            // orderPart.setLength(); // 宽度
            // orderPart.setWidth(); // 长度


            String code = orderBom.getPlmId();
            if (code.endsWith("_170")) {
                code = code.substring(0, code.indexOf("_170"));
            }
            ImportMbdDxf importMbdDxf = importMbdDxfMapper.lambdaQuery().eq(ImportMbdDxf::getPlmid, code).orderByDesc(ImportMbdDxf::getDocVersion).last("limit 1").one();
            orderPart.setDrawStatus(1); // 是否制图就绪，默认 未就绪
            orderPart.setVersionNum(importMbdDxf != null ? importMbdDxf.getDocVersion() : null); // 图纸版本号
            orderPart.setDrawUpdateTime(null); // 图纸更新时间

            orderParts.add(orderPart);
            hasPartMap.put(orderPart.getPlmId(), orderPart);
        }
        if (!CollUtil.isEmpty(orderParts)) {
            orderPartMapper.insertBatchSomeColumn(orderParts);
        }

    }

    public void savePhase(List<OrderPhase> orderPhaseList) {
        if(CollUtil.isEmpty(orderPhaseList)){
            return ;
        }
        orderPhaseMapper.insertBatchSomeColumn(orderPhaseList);
    }


    public void saveOrder(Order order, List<OrderExternalSyncErrorResVo> errorList) {
        Integer extracted = getSerialNum(order.getConstructNo(), order.getOrderType());
        order.setSerialNum(extracted);
        order.setSerialCode(String.format("%04d-", order.getSerialNum()) + order.getConstructNo());


        Customer customer = customerMapper.selectById(3);
        if(customer == null){
            throw SyExceptionUtils.e("没有找到该客户");
        }

        order.setCustomerId(3);
        order.setCustomerCode(customer.getMyCode());
        order.setCustomerName(customer.getName());
        order.setOrderPriority(1);
        order.setOrderWeight(1);

        orderMapper.insert(order);
    }

    public Integer getSerialNum(String constructNo, Integer orderType) {
        List<Order> list = orderMapper.lambdaQuery()
                .eq(Order::getConstructNo, constructNo)
                .eq(Order::getOrderType, orderType)
                .list();

        if (CollUtil.isNotEmpty(list)) {
            if (list.get(0).getSerialNum() == null) {
                Order max = orderMapper.lambdaQuery().eq(Order::getOrderType, orderType).orderByDesc(Order::getSerialNum).last(" limit 1").one();
                int serialCode = 0;
                if (max != null && max.getSerialNum() != null) {
                    serialCode = max.getSerialNum();
                }

                return serialCode + 1;
            } else {
                return list.get(0).getSerialNum();
            }
        } else {
            Order max = orderMapper.lambdaQuery().eq(Order::getOrderType, orderType).orderByDesc(Order::getSerialNum).last(" limit 1").one();
            int serialCode = 0;
            if (max != null && max.getSerialNum() != null) {
                serialCode = max.getSerialNum();
            }
            return serialCode + 1;

        }
    }

    public Order conversionOrder(ImportErpOrder importErpOrder, ImportErpBom currentBom, ImportErpMater importErpMater, List<OrderExternalSyncErrorResVo> errorList) {
        Order order = new Order();
        order.setOrderCode(importErpOrder.getOrderCode());
        order.setConstructNo(importErpOrder.getOrderCode());
        order.setMaterCode(currentBom.getGraphNo());
        order.setMaterName(currentBom.getMaterialName());
        order.setOrderQty(NumberUtil.parseInt(importErpOrder.getQty()));

        int max = NumberUtil.parseInt(currentBom.getReqQty());
        order.setOrderQty(Math.max(max, order.getOrderQty()));

        order.setFinishQty(0);
        if (importErpOrder.getOrderCode().startsWith("J")) {
            order.setOrderType(4);
        } else {
            order.setOrderType(1);
        }

        order.setOrderStatus(1);
        order.setOrderDateTime(importErpOrder.getAssignDate());
        order.setDeliveryDateTime(importErpOrder.getDeliTime());
        order.setPlmId(importErpMater.getPlmId());

        Customer customer = customerMapper.selectById(3);
        if(customer == null){
            throw SyExceptionUtils.e("没有找到该客户");
        }

        order.setCustomerId(3);
        order.setCustomerCode(customer.getMyCode());
        order.setCustomerName(customer.getName());
        order.setOrderPriority(1);
        order.setOrderWeight(1);

        if(order.getOrderType().equals(1)){
            order.setSuffix(OrderUtils.partType(importErpMater.getPlmId(), currentBom.getMaterialName()));
        }

        Factory line = factoryMapper.lambdaQuery().eq(Factory::getType, 2).eq(Factory::getMyCode, WorkshopProp.DEFAULT_LINE_CODE).one();
        order.setLineId(line.getId());

        return order;
    }

    public List<OrderPhase> conversionPhase(Order order, List<OrderBom> bomList, List<ImportErpWorkOrderDetail> workOrderDetailList, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {

        List<Phase> phaseList = phaseMapper.lambdaQuery().list();
        Map<Integer, Phase> phaseIdMap = phaseList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<PhaseJob> phaseJobList = phaseJobMapper.lambdaQuery().list();
        Map<Integer, PhaseJob> phaseJobIdMap = phaseJobList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<PhaseJobRef> phaseJobRefList = phaseJobRefMapper.lambdaQuery().list();
        Map<String, List<PhaseJobRef>> phaseCodeRefJob = phaseJobRefList.stream().sorted(Comparator.comparing(PhaseJobRef::getSeq)).collect(Collectors.groupingBy(e -> phaseIdMap.get(e.getPhaseId()).getMyCode(), LinkedHashMap::new, Collectors.toList()));
        Map<String, List<PhaseJob>> phaseJobMap = new HashMap<>();
        for (String s : phaseCodeRefJob.keySet()) {
            phaseJobMap.put(s, new ArrayList<>());
            List<PhaseJobRef> phaseJobRefs = phaseCodeRefJob.get(s);
            if(CollUtil.isNotEmpty(phaseJobRefs)){
                phaseJobMap.put(s, phaseJobRefs.stream()
                        .sorted(Comparator.comparing(PhaseJobRef::getSeq))
                        .map(e -> {
                            return phaseJobIdMap.get(e.getPhaseJobId());
                        })
                        .collect(Collectors.toList()));
            }
        }

        Map<String, Map<String, ImportErpMapping>> erpMesOpMappingMap = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));

        Map<String, Map<String, List<ImportErpWorkOrderDetail>>> workOrderCodeMaterialCodeMap = workOrderDetailList.stream()
                .collect(
                        Collectors.groupingBy(
                                ImportErpWorkOrderDetail::getWorkOrderCode,
                                Collectors.groupingBy(
                                        ImportErpWorkOrderDetail::getMaterialCode
                                )
                        )
                );

        List<OrderPhase> orderPhaseList = new ArrayList<>();
        bomList.sort(Comparator.comparing(OrderBom::getPlmId));

        Map<Integer, OrderBom> orderBomMap = bomList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        for (OrderBom bom : bomList) {

            Map<String, List<ImportErpWorkOrderDetail>> stringListMap = workOrderCodeMaterialCodeMap.get(bom.getWorkOrderCode());
            int phaseSeq = 1;

            if (bom.getMaterType() == null) {
                errorList.add(new OrderExternalSyncErrorResVo(2, "材质或规格为空", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                continue;
            }

            if(CollUtil.isEmpty(stringListMap) && bom.getMaterType().equals("Assembly") && !StringUtils.hasText(bom.getWorkChain())){
                bom.setWorkChain(WorkshopProp.WW_PHASE_CODE);
                orderBomMapper.updateById(bom);

                OrderPhase topPhase = PhaseUtils.getWeiwaiPhase(
                        order.getId(), bom.getId(), bom.getWorkChain(),
                        phaseSeq, bom.getPlmId(), bom.getMaterName()
                );
                phaseSeq++;
                orderPhaseMapper.insert(topPhase);
            }

            if (stringListMap == null) {
                continue;
            }

            List<ImportErpWorkOrderDetail> importErpWorkOrderDetails = stringListMap.get(bom.getBomCode());
            if (importErpWorkOrderDetails == null) {
                continue;
            }

            BigDecimal reduce = importErpWorkOrderDetails.stream().reduce(BigDecimal.ZERO, (a, b) -> a.add(new BigDecimal(b.getSdgs() == null? "0" : b.getSdgs())), BigDecimal::add);
            if (!bom.getWorkChain().equals("WL") && reduce.compareTo(BigDecimal.ZERO) == 0) {

                bom.setMaterType("Component");
                bom.setWorkChain("WL");//外协件定值
                bom.setReadyType(2);
                orderBomMapper.updateById(bom);
                continue;
            }

            if (bom.getMaterType().equals("Platepart")) {
                OrderPhase llPhase = PhaseUtils.genLingliaoPhase(order.getId(), bom.getId(), bom.getWorkChain(), phaseSeq, bom.getPlmId(), bom.getMaterName());
                phaseSeq++;
                orderPhaseList.add(llPhase);
            }

            Map<String, Integer> phaseCount = new HashMap<>();
            importErpWorkOrderDetails.sort(Comparator.comparing(ImportErpWorkOrderDetail::getSeq));
            for (ImportErpWorkOrderDetail detail : importErpWorkOrderDetails) {
                OrderPhase phase = new OrderPhase();
                phase.setOrderId(order.getId());
                phase.setBomId(bom.getId());

                //工时取sdgs
                if (detail.getSdgs() != null) {
                    phase.setWorkTime(new BigDecimal(detail.getSdgs()).multiply(new BigDecimal(60)).setScale(0, RoundingMode.UP).intValue());
                } else {
                    phase.setWorkTime(0);
                }
                phase.setOriWorkTime(phase.getWorkTime());

                //detailEntity.setProdSn(z.getSn());
                phase.setWorkChain(bom.getWorkChain());
                phase.setMaterNo(bom.getPlmId());
                phase.setMaterName(detail.getMaterialName());
                phase.setOp(detail.getOp());
                phase.setOpCode(detail.getOpCode());
                if(!detail.getOpCode().trim().startsWith("170")){
                    continue;
                }
                if (erpMesOpMappingMap.get(detail.getOpCode()) == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
//                    throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode().trim() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                    continue;

                }
                ImportErpMapping importErpMapping = null;
                if (detail.getOpCode().startsWith("129")) {
                    importErpMapping = erpMesOpMappingMap.get("129002").get("Z206");
                } else {
                    importErpMapping = erpMesOpMappingMap.get(detail.getOpCode()).get(detail.getOp());
                }

                if (importErpMapping == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                    continue;
                }
                Integer count = phaseCount.compute(importErpMapping.getMesWorkPhase(), (k, v) -> v == null ? 0 : v + 1);
                String phaseCodeCount = importErpMapping.getMesWorkPhase();

                if (count > 0) {
                    phaseCodeCount = importErpMapping.getMesWorkPhase() + String.format("%02d", count);
                }
                phase.setPhaseCode(phaseCodeCount);
                phase.setPhaseSeq(phaseSeq++);
                phase.setPhaseName(importErpMapping.getApsPhaseName());
                phase.setWorkGroupNumber(importErpMapping.getMesWorkCenter());

                if(phase.getWorkTime().compareTo(0) > 0){
                    // 工序任务处理
                    List<PhaseJob> job = phaseJobMap.get(phase.getPhaseCode());
                    if (CollUtil.isNotEmpty(job)) {
                        int jobTime = TaskTimeUtils.calcJobTime(phase, job);
                        phase.setOriWorkTime(phase.getWorkTime());
                        phase.setWorkTime(phase.getWorkTime() + jobTime);
                    }
                }

                orderPhaseList.add(phase);

                if(StringUtils.hasText(detail.getWiremodel()) && !detail.getWiremodel().trim().equals("null")){
                    phase.getAttr().put("type", "wire");
                    phase.getAttr().put("wiremodel", detail.getWiremodel());
                    phase.getAttr().put("wirenumber", detail.getWirenumber());
                    phase.getAttr().put("wirequota", detail.getWirequota());
                }

                if(bom.getWorkChain().equals("WL") && (phase.getPhaseCode().equals("JG") || phase.getPhaseCode().equals("HG"))){
                    errorList.add(new OrderExternalSyncErrorResVo(2, detail.getMaterialName() + detail.getMaterialCode() + "数据异常, 类型识别为WL，但是有切割工序", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                }
            }

            if (bom.getPid() != null ) {
                if(bom.getMaterType().equals("Platepart") || (bom.getMaterType().equals("Assembly") && !MkPartUtils.supportKjPhase(bom.getPlmId(), bom.getMaterName()))){
                    OrderBom parentBom = orderBomMap.get(bom.getPid());
                    if (MkPartUtils.supportKjPhase(parentBom.getPlmId(), parentBom.getMaterName())) {

                        OrderPhase llPhase = PhaseUtils.genKujianPhase(order.getId(), bom.getId(), bom.getWorkChain(), phaseSeq, bom.getPlmId(), bom.getMaterName());
                        phaseSeq++;
                        orderPhaseList.add(llPhase);

                    }
                }
            }
        }

        return orderPhaseList;
    }

    public List<ImportErpWorkOrderDetail> getWorkOrderDetailMap(Integer erpOrderId, List<String> materCodeList) {

        QueryWrapper<ImportErpWorkOrderDetail> query = Wrappers.query();
        query.in("material_code", materCodeList);
        query.eq("erp_order_id", erpOrderId);
        return importErpWorkOrderDetailMapper.selectList(query);

    }

    public List<ImportErpBom> findAllTree(ImportErpOrder order) {
        return importErpBomMapper.selectList(Wrappers.<ImportErpBom>query().eq("erp_order_id", order.getId()));
    }

    public List<ImportErpWorkOrder> getWorkOrderMap(Integer erpOrderId, List<String> bomChildren) {

        LambdaQueryWrapper<ImportErpWorkOrder> query = Wrappers.lambdaQuery();
        query.in(ImportErpWorkOrder::getMaterialCode, bomChildren);
        query.eq(ImportErpWorkOrder::getErpOrderId, erpOrderId);
        return importErpWorkOrderMapper.selectList(query);

    }

    public List<ImportErpMater> getMaterMap(Integer erpOrderId, List<String> materCodeList) {

        QueryWrapper<ImportErpMater> query = Wrappers.query();
//        query.in("material_code", materCodeList);// 注意，此处不要取部分，要取全部
        query.eq("erp_order_id", erpOrderId);
        return importErpMaterMapper.selectList(query);
    }

    public List<OrderBom> conversionBom(Order order, ImportErpOrder importErpOrder, List<ImportErpBom> allBomTree, List<ImportErpBom> bomChildren, List<ImportErpMater> erpMaterList, List<ImportErpWorkOrder> erpWorkOrderList, List<ImportErpWorkOrderDetail> workOrderDetailListAll, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {
        Map<String, Map<String, ImportErpMapping>> erpMesOpMapping = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));
        Map<String, List<ImportErpBom>> bomPmCodeMap = allBomTree.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        Map<String, ImportErpMater> materCodeMap = erpMaterList.stream().collect(Collectors.toMap(ImportErpMater::getMaterialCode, Function.identity(), (e1, e2) -> e1));
        Map<String, List<ImportErpWorkOrder>> workOrderCodeMap = erpWorkOrderList.stream().collect(Collectors.groupingBy(ImportErpWorkOrder::getMaterialCode));
        Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap = workOrderDetailListAll.stream().collect(Collectors.groupingBy(ImportErpWorkOrderDetail::getMaterialCode));
        Map<String, ImportErpBom> parentBom = allBomTree.stream().collect(Collectors.toMap(ImportErpBom::getMaterialCode, Function.identity(), (e1, e2) -> e1));

        List<OrderBom> orderBomList = new ArrayList<>();

        Optional<ImportErpBom> firstOptional = bomChildren.stream().filter(e -> e.getIsTop() == 1).findFirst();
        if (!firstOptional.isPresent()) {
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点"));
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点：" + importErpOrder.getOrderCode(), importErpOrder.getOrderCode(), null, null, null, null,null, null, null, null, null));
            throw SyExceptionUtils.e("找不到BOM的根节点!");
        }
        ImportErpBom importErpBom = firstOptional.get();
        OrderBom top = swap(order, importErpBom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, null, errorList);
        String pattern = ".+" + WorkshopProp.PH_PATTERN;
        if (order.getOrderType() == 1 && !order.getMaterCode().matches(pattern)) {
            OrderBom o = orderBomMapper.lambdaQuery().eq(OrderBom::getMaterCode, order.getMaterCode()).eq(OrderBom::getOrderId, order.getId()).one();
            if (o == null) {
                OrderBom orderBom = new OrderBom();
                orderBom.setFactoryNo("170");
                orderBom.setOrderId(order.getId());
                orderBom.setMaterName(order.getMaterName());
                orderBom.setMaterCode(order.getMaterCode());

                int div = Integer.parseInt(importErpOrder.getQty()) / order.getOrderQty();
                if(Integer.parseInt(importErpOrder.getQty()) % order.getOrderQty() != 0){
                    throw SyExceptionUtils.e("订单数量必须为整数倍!");
                }

                if(div < 1){
                    throw SyExceptionUtils.e("当前数量必须大于等于订单数量!");
                }

                orderBom.setPartCount(new BigDecimal(div));
                orderBom.setTotalCount(orderBom.getPartCount());
                orderBom.setBomCode(order.getMaterCode());
                orderBom.setPlmId(order.getMaterCode());
                orderBom.setMaterType("Assembly");
                orderBom.setLevel(1);
                orderBom.setReadyType(1);
                orderBom.setDrawing(orderBom.getDrawing());

                StringBuilder sb = new StringBuilder();

                ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
                while (currentParent != null) {
                    ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
                    if (importErpMater1 == null) {
                        // throw SyExceptionUtils.e("没有找到路径!");
//                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode()));
                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode(), importErpOrder.getOrderCode(), currentParent.getWorkOrderCode(), currentParent.getMaterialCode(), currentParent.getMaterialName(), null,String.format("%s%s", currentParent.getMaterial(), currentParent.getGrade()), currentParent.getPerReqQty(), currentParent.getPmCode(), currentParent.getStatusId(), null));
                    } else {
                        sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
                    }
                    currentParent = parentBom.get(currentParent.getPmCode());
                }

                orderBom.setAssemblyPath(sb.toString());
                orderBom.setTopFlag(1);
                orderBom.setWorkChain(WorkshopProp.WW_PHASE_CODE);
                orderBomMapper.insert(orderBom);

                OrderPhase topPhase = PhaseUtils.getWeiwaiPhase(
                        order.getId(), orderBom.getId(), orderBom.getWorkChain(),
                        1, orderBom.getMaterCode(), orderBom.getMaterName()
                );
                orderPhaseMapper.insert(topPhase);

                o = orderBom;
            }
            orderBomList.add(o);
            top.setPid(o.getId());

            orderBomList.add(top);
            top.setLevel(2);
            top.setTopFlag(0);
            top.setAssemblyPath(o.getAssemblyPath() + "/" + top.getDrawing());
            if(!StringUtils.hasText(top.getWorkChain())){
                top.setWorkChain(WorkshopProp.WW_PHASE_CODE);
            }
            orderBomMapper.insert(top);

            if (top.getWorkChain().equals(WorkshopProp.WW_PHASE_CODE)) {
//                OrderPhase llPhase =PhaseUtils.genKujianPhase(
//                        order.getId(), top.getId(), top.getWorkChain(),
//                        1, top.getMaterCode(), top.getMaterName()
//                );
//
//                orderPhaseMapper.insert(llPhase);

                OrderPhase topWwPhase = PhaseUtils.getWeiwaiPhase(
                        order.getId(), top.getId(), top.getWorkChain(),
                        1, top.getMaterCode(), top.getMaterName()
                );
                orderPhaseMapper.insert(topWwPhase);
            }

        } else {
            orderBomList.add(top);
            orderBomMapper.insert(top);
        }


        Map<String, List<ImportErpBom>> collect = bomChildren.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        List<OrderBom> orderBoms = Lists.newArrayList(top);

        while (!orderBoms.isEmpty()) {
            List<OrderBom> temp = Lists.newArrayList();
            for (OrderBom orderBom : orderBoms) {

                List<ImportErpBom> orderBoms1 = collect.get(orderBom.getBomCode());
                if (orderBoms1 == null) {
                    continue;
                }

                Map<String, OrderBom> map = new HashMap<>();
                for (ImportErpBom bom : orderBoms1) {
                    OrderBom swap = swap(order, bom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, orderBom, errorList);
//                    if(orderBom.getWorkChain().equals("WL") && swap.getWorkChain().equals("WL")){
//                        continue;
//                    }

                    OrderBom bomHas = map.get(swap.getPlmId());
                    if(bomHas != null){
                        continue;
                    }
                    map.put(swap.getPlmId(), swap);

                    temp.add(swap);
                    orderBomList.add(swap);
                    orderBomMapper.insert(swap);
                }
            }
            orderBoms = temp;

        }

        orderBomList.sort(Comparator.comparing(OrderBom::getBomCode));
        return orderBomList;


    }

    public OrderBom swap(Order order, ImportErpBom bom, Map<String, ImportErpMater> materCodeMap, Map<String, List<ImportErpWorkOrder>> workOrderCodeMap, Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap, Map<String, List<ImportErpBom>> bomPmCodeMap, Map<String, Map<String, ImportErpMapping>> erpMesOpMapping, Map<String, ImportErpBom> parentBom, OrderBom parent, List<OrderExternalSyncErrorResVo> errorList) {

        OrderBom orderBom = new OrderBom();
        orderBom.setFactoryNo("170");
        orderBom.setOrderId(order.getId());
        orderBom.setPackCenter(bom.getPickCenter());
        orderBom.setMaterName(bom.getMaterialName());
        orderBom.setStandards(bom.getGrade());
        orderBom.setErpCode(bom.getMaterialCode());
        orderBom.setErpParentCode(bom.getPmCode());
        orderBom.setPartCount(NumberUtil.round(bom.getPerReqQty(), 0));
        orderBom.setTopFlag(bom.getIsTop());
        orderBom.setBomCode(bom.getMaterialCode());
        orderBom.setParentBomCode(bom.getPmCode());

        if (parent == null) {
            orderBom.setTotalCount(orderBom.getPartCount());
            orderBom.setLevel(1);
        } else {
            orderBom.setTotalCount(parent.getTotalCount().multiply(orderBom.getPartCount()));
            orderBom.setLevel(parent.getLevel() + 1);
        }

        ImportErpMater importErpMater = materCodeMap.get(bom.getMaterialCode());
        if (importErpMater == null) {
//            throw SyExceptionUtils.e("找不到对应的物料信息");
            orderBom.setMaterCode(bom.getGraphNo());
            if(StringUtils.hasText(orderBom.getMaterCode())){
                orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
            }
            orderBom.setPlmId(orderBom.getMaterCode());
            orderBom.setDrawing(orderBom.getMaterCode());
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(2);
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
//            errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + bom.getMaterialCode(), order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), null));
            return orderBom;
        }

        orderBom.setMaterCode(importErpMater.getPaintCode());
        if(StringUtils.hasText(orderBom.getMaterCode())){
            orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
        }


        orderBom.setPlmId(importErpMater.getPlmId());
        if (orderBom.getPlmId() == null) {
            orderBom.setPlmId("");
        }
        if(StringUtils.hasText(orderBom.getPlmId())){
            orderBom.setPlmId(orderBom.getPlmId().replaceAll("/", "-"));
        }

        if (importErpMater.getNetWeight() != null) {
            orderBom.setMaterWeight(NumberUtil.round(importErpMater.getNetWeight(), 2));
        }

        orderBom.setDrawing(importErpMater.getPaintCode());
        if(StringUtils.hasText(orderBom.getDrawing())){
            orderBom.setDrawing(orderBom.getDrawing().replaceAll("/", "-"));
        }


        List<ImportErpWorkOrder> workOrderList = workOrderCodeMap.get(bom.getMaterialCode());
        ImportErpWorkOrder workOrder = null;
        if (CollUtil.isNotEmpty(workOrderList)) {
            workOrder = findDueDate(workOrderList);
            if (workOrder != null) {
                orderBom.setDueDate(workOrder.getPlanEndTime());
            }
        }

        if (workOrder == null) {
            workOrder = new ImportErpWorkOrder();
            workOrder.setIsComponent("1");
            workOrder.setWorkOrderCode("WO-XXXXXXX");
            workOrder.setWorkOrderType("1");
//                    orderBom.setDueDate(bom.getMarkDate());// 代码有问题，ERP没这个字段，所有注释
        }


        List<ImportErpWorkOrderDetail> workOrderDetailList = workOrderDetailMap.get(bom.getMaterialCode());
        // 如果无工序明细，则为外协件
        if (workOrderDetailList == null) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : 1);
        }

        String spec = importErpMater.getSpec();//.replaceAll(REGEX_CHINESE, "");
        if (spec != null) {
            if (spec.contains("组件")) {
                orderBom.setMaterType("Assembly"); // 组件类型，Assembly
            } else if (workOrderDetailList == null) {
                //如果无工序明细，则为外协件
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            } else if (spec.contains("δ")) {
                orderBom.setMaterType("Platepart");//Platepart
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);

                //施工单 物料号  获取 工单bom
                List<ImportErpBom> plateList = bomPmCodeMap.get(bom.getMaterialCode());
                if (plateList == null || plateList.isEmpty()) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "找不到对应的板材材质或规格信息", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("找不到对应的板材材质或规格信息");
                } else {
                    ImportErpBom plateBom = plateList.get(0);
                    if (StringUtils.hasText(plateBom.getMaterial()) && StringUtils.hasText(plateBom.getGrade())) {
                        orderBom.setTexture(plateBom.getMaterial());//材质
                        String str = plateBom.getGrade().replace("δ", "");
                        try {
                            orderBom.setMaterHigh(NumberUtil.round(str, 0).intValue());//厚度

                        } catch (Exception e) {
                            e.printStackTrace();
                            throw e;
                        }
                    } else {
                        errorList.add(new OrderExternalSyncErrorResVo(2, "材质或规格为空", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                        return orderBom;
//                        throw SyExceptionUtils.e("材质或规格为空");
                    }


                }
            } else {
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            }
        }

        //工单类型0-自制；1-外协
        if (workOrder.getWorkOrderType().equals("1")) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : null);
        }

        if (orderBom.getMaterType() == null) {
            errorList.add(new OrderExternalSyncErrorResVo(2, "无法判断物料类型!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
            return orderBom;
//            throw SyExceptionUtils.e("无法判断物料类型!");
        }

//            orderBom.setParentMaterNo(orderBom.getDrawing());
        //获取工序链
        if (!orderBom.getMaterType().equals("Component")) {
            String workChain = getWorkChain(workOrderDetailList, erpMesOpMapping, workOrder.getWorkOrderCode(), orderBom, errorList);
            orderBom.setWorkChain(workChain);
        }


        //ERP工单号
        orderBom.setWorkOrderCode(workOrder.getWorkOrderCode());

        // MES需要的路径，如果没用请注释
        if (orderBom.getTopFlag().equals(1)) {
            StringBuilder sb = new StringBuilder();

            ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
            while (currentParent != null) {
                ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
                if (importErpMater1 == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "没有找到路径!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("没有找到路径!");
                }
                sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
                currentParent = parentBom.get(currentParent.getPmCode());
            }

            orderBom.setAssemblyPath(sb.toString());
        } else {
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
        }

        orderBom.setReadyType(orderBom.getWorkChain().equals("WL") ? 2 : 1);

        return orderBom;
    }

    public String getWorkChain(List<ImportErpWorkOrderDetail> allWorkOrderDetailList, Map<String, Map<String, ImportErpMapping>> erpMesOpMappingMap, String workOrderCode, OrderBom bom, List<OrderExternalSyncErrorResVo> errorList) {
        String workChain = "";
        if (CollUtil.isEmpty(allWorkOrderDetailList)) {
            return workChain;
        }

        List<ImportErpWorkOrderDetail> detailList = allWorkOrderDetailList
                .stream()
                .filter(e -> !"70020604".equals(e.getOpCode()))
                .filter(e -> !"Z105".equals(e.getOp()))
                .filter(e -> workOrderCode.equals(e.getWorkOrderCode()))
                .sorted(Comparator.comparing(ImportErpWorkOrderDetail::getSeq))
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(detailList)) {
            return workChain;
        }

        Map<String, Integer> phaseCount = new HashMap<>();
        for (ImportErpWorkOrderDetail detail : detailList) {

            if (!StringUtils.hasText(detail.getOpCode())) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
//                errorList.add("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }

            if(!detail.getOpCode().trim().startsWith("170")){
                continue;
            }

            if (!StringUtils.hasText(detail.getOp())) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
//                errorList.add("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }

            if (erpMesOpMappingMap.get(detail.getOpCode()) == null) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }
            ImportErpMapping importErpMapping = erpMesOpMappingMap.get(detail.getOpCode()).get(detail.getOp());

            if (importErpMapping == null) {
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
            } else {
                String str = importErpMapping.getMesWorkPhase();
                Integer count = phaseCount.compute(str, (k, v) -> v == null ? 0 : v + 1);
                String phaseCodeCount = str + "-";
                if (count > 0) {
                    phaseCodeCount = str + String.format("%02d", count) + "-";
                }
                workChain += phaseCodeCount;
            }
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(workChain)) {
            workChain = workChain.substring(0, workChain.length() - 1);
        } else {
//            throw SyExceptionUtils.e("工序链生成失败！");
            errorList.add(new OrderExternalSyncErrorResVo(4, "工序链生成失败!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
        }


        return workChain;
    }

    public ImportErpWorkOrder findDueDate(List<ImportErpWorkOrder> infoList) {
        if (infoList.size() == 1) {
            return infoList.get(0);

        }

        //过滤掉 3 和4  已取消的
        List<ImportErpWorkOrder> collectList = infoList
                .stream()
                .filter(s -> !s.getWorkOrderState().equals("3") && !s.getWorkOrderState().equals("4"))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collectList)) {
            return collectList.get(0);
        }

        //如果没有 就获取 计划开始时间不为空的
        for (ImportErpWorkOrder orderInfo : infoList) {
            if (orderInfo.getPlanStartTime() != null) {
                return orderInfo;
            }
        }
        return null;
    }

    public List<ImportErpBom> findBomChildren(ImportErpBom currentBom) {
//
//        QueryWrapper<ImportErpBom> query = Wrappers.query();
//        query.ne("bom.status_id", "R");// 'Z21-010Z'
//        query.eq("bom.erp_order_id", currentBom.getErpOrderId());
////        query.eq("mater.erp_order_id", currentBom.getErpOrderId());
//        query.eq("bom.deleted", 0);
//        query.orderByAsc("mater.paint_code");
        List<ImportErpBom> importErpBoms = importErpBomMapper.tree(currentBom.getErpOrderId());

        Map<String, List<ImportErpBom>> pmCodeList = importErpBoms.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));

        List<ImportErpBom> l = new ArrayList<>();

        List<ImportErpBom> temp = new ArrayList<>();
        temp.add(currentBom);
        currentBom.setIsTop(1);

        while (!temp.isEmpty()) {
            List<ImportErpBom> t = new ArrayList<>();
            for (ImportErpBom importErpBom : temp) {
                List<ImportErpBom> importErpBoms1 = pmCodeList.get(importErpBom.getMaterialCode());
                if (importErpBoms1 == null) {
                    continue;
                }
                for (ImportErpBom erpBom : importErpBoms1) {
                    erpBom.setIsTop(0);
                }
                t.addAll(importErpBoms1);
            }
            l.addAll(temp);
            temp = t;
        }
        return l;
    }

    @Override
    public String getMyCode() {
        return ERP_CODE;
    }

    @Transactional
    @Override
    public void externalBomDel(OrderExternalBomDelReqVo reqVo) {
        for (Integer id : reqVo.getId()) {
            importErpBomMapper.realDelete(id);
        }
    }
}
